home *** CD-ROM | disk | FTP | other *** search
/ Inter.Net 55-1 / Inter.Net 55-1.iso / CBuilder / Setup / BCB / data.z / time.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-09  |  17.2 KB  |  613 lines

  1. #ifndef __TIME_CC
  2. #define __TIME_CC
  3. #pragma option push -b -a4 -Vx- -Ve- -w-inl -w-aus -w-sig
  4. /***************************************************************************
  5.  *
  6.  * time.cc - Definitions for the Standard Library time facets
  7.  *
  8.  *
  9.  ***************************************************************************
  10.  *
  11.  * (c) Copyright 1994, 1995 Rogue Wave Software, Inc.
  12.  * ALL RIGHTS RESERVED *
  13.  * The software and information contained herein are proprietary to, and
  14.  * comprise valuable trade secrets of, Rogue Wave Software, Inc., which
  15.  * intends to preserve as trade secrets such software and information.
  16.  * This software is furnished pursuant to a written license agreement and
  17.  * may be used, copied, transmitted, and stored only in accordance with
  18.  * the terms of such license and with the inclusion of the above copyright
  19.  * notice.  This software and information or any other copies thereof may
  20.  * not be provided or otherwise made available to any other person.
  21.  *
  22.  * Notwithstanding any other lease or license that may pertain to, or
  23.  * accompany the delivery of, this computer software and information, the
  24.  * rights of the Government regarding its use, reproduction and disclosure
  25.  * are as set forth in Section 52.227-19 of the FARS Computer
  26.  * Software-Restricted Rights clause.
  27.  * 
  28.  * Use, duplication, or disclosure by the Government is subject to
  29.  * restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
  30.  * Technical Data and Computer Software clause at DFARS 252.227-7013.
  31.  * Contractor/Manufacturer is Rogue Wave Software, Inc.,
  32.  * P.O. Box 2328, Corvallis, Oregon 97339.
  33.  *
  34.  * This computer software and information is distributed with "restricted
  35.  * rights."  Use, duplication or disclosure is subject to restrictions as
  36.  * set forth in NASA FAR SUP 18-52.227-79 (April 1985) "Commercial
  37.  * Computer Software-Restricted Rights (April 1985)."  If the Clause at
  38.  * 18-52.227-74 "Rights in Data General" is specified in the contract,
  39.  * then the "Alternate III" clause applies.
  40.  *
  41.  **************************************************************************/
  42.  
  43. #ifndef _RWSTD_NO_NAMESPACE
  44. namespace __rwstd {
  45. using namespace std;
  46. #endif
  47.  
  48. // --------------------------------------
  49. // Template time_reader member templates.
  50. // --------------------------------------
  51.  
  52. template <class charT,class InputIterator>
  53. time_reader<charT,InputIterator>::time_reader
  54.     (InputIterator& in,InputIterator& end,ios_base& io):
  55.     digit_reader<charT,InputIterator>(in,end,io),
  56. #ifndef _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE
  57.     timp(use_facet<timepunct<charT> >(io.getloc()))
  58. #else
  59. //  timp(use_facet(io.getloc(),(timepunct<charT>*)0))
  60.     timp(ms_idiocy(io))
  61. #endif
  62. {
  63.   // Don't recognize signs on any numeric input.
  64.   this->is_signed=false;
  65. }
  66.  
  67. template <class charT,class InputIterator>
  68. bool time_reader<charT,InputIterator>::
  69.     get_time_pattern (const string_type &patt,tm *time)
  70. {
  71.   enum {
  72.     edit_year = 0x01,
  73.     edit_month = 0x02,
  74.     edit_century = 0x04
  75.   };
  76.  
  77.   int post_edits=0;
  78.   const charT *p=patt.c_str(),*patt_end=p+patt.length();
  79.   for ( ; p<patt_end; p++) {
  80.     switch (this->ctyp.narrow(*p,' ')) {
  81.      case '%':
  82.       {
  83.         int *iresult;
  84.         const keyword_map<charT> *keywords=NULL;
  85.  
  86.         switch (this->ctyp.narrow(*++p,' ')) {
  87.          case 'a':
  88.          case 'A':
  89.           // Day of week (abbreviated or not).
  90.           keywords=&get_day_map(timp);
  91.           iresult=&time->tm_wday;
  92.           break;
  93.          case 'b':
  94.          case 'B':
  95.           // Month name (abbreviated or not).
  96.           keywords=&get_month_map(timp);
  97.           iresult=&time->tm_mon;
  98.           break;
  99.          case 'm':
  100.           // Numeric month, comes in 1 higher than the number we want.
  101.           post_edits|=edit_month;
  102.           iresult=&time->tm_mon;
  103.           break;
  104.          case 'c':
  105.           // Full date, time and year in default format.
  106.           return get_time_pattern(get_patt_string(timp,2),time);
  107.          case 'd':
  108.           // Day of month.
  109.           iresult=&time->tm_mday;
  110.           break;
  111.          case 'H':
  112.           // Hours.
  113.           iresult=&time->tm_hour;
  114.           break;
  115.          case 'M':
  116.           // Minutes.
  117.           iresult=&time->tm_min;
  118.           break;
  119.          case 'S':
  120.           // Seconds.
  121.           iresult=&time->tm_sec;
  122.           break;
  123.          case 'Y':
  124.           // Year with Century.
  125.           post_edits|=edit_year;
  126.           iresult=&time->tm_year;
  127.           break;
  128.          case 'y':
  129.           // 2-digit Year without Century.
  130.           post_edits|=(edit_year|edit_century);
  131.           iresult=&time->tm_year;
  132.           break;
  133.          default:
  134.           // All other format characters are not supported on input.
  135.           return false;
  136.         }
  137.  
  138.         if (keywords) {
  139.           if ((*iresult=get_keyword(*keywords))<0)
  140.             return false;
  141.         } else
  142.           *iresult=to_ulong(this->get_int_digits());
  143.       }
  144.       break;
  145.  
  146.      default:
  147.       if (!this->at_end() && *this->in==*p)
  148.         this->in++;
  149.       else
  150.         return false;
  151.     }
  152.  
  153.     if (this->error)
  154.       return false;
  155.   }
  156.  
  157.   if (post_edits&edit_year)
  158.     if (post_edits&edit_century && time->tm_year<100)
  159.       ; // 2-digit year is already relative to 1900
  160.     else
  161.       time->tm_year-=1900;
  162.  
  163.   if (post_edits&edit_month)
  164.     time->tm_mon--;
  165.  
  166.   return true;
  167. }
  168.  
  169.  
  170. #ifndef _RWSTD_NO_NAMESPACE
  171. } namespace std {
  172. #endif
  173.  
  174.  
  175. // -----------------------------------------------------
  176. // Facet time_get<charT,InputIterator> member templates.
  177. // -----------------------------------------------------
  178.  
  179. template <class charT, class InputIterator>
  180. locale::id time_get<charT,InputIterator>::id;
  181.  
  182. template <class charT, class InputIterator>
  183. time_get<charT,InputIterator>::~time_get() { }
  184.  
  185. template <class charT, class InputIterator>
  186. time_base::dateorder time_get<charT,InputIterator>::do_date_order () const
  187. {
  188.   // We would prefer to return a value that matches the date format defined
  189.   // in the timepunct facet in the caller's locale, but we can't get there
  190.   // from here ...
  191.   return no_order;
  192. }
  193.  
  194. template <class charT, class InputIterator>
  195. _TYPENAME time_get<charT,InputIterator>::iter_type
  196. time_get<charT,InputIterator>::do_get_time (InputIterator in,
  197.     InputIterator end, ios_base& io, ios_base::iostate& err, tm* time) const
  198. {
  199.   __RWSTD::time_reader<charT,InputIterator> reader(in,end,io);
  200.   err=ios_base::goodbit;
  201.  
  202.   // Parse according to pattern 1 (strftime '%X' -- default time pattern)
  203.   if (!reader.get_time_pattern(reader.get_patt_string(reader.timp,1),time))
  204.     err=ios_base::failbit;
  205.  
  206.   if (reader.reached_end)
  207.     err|=ios_base::eofbit;
  208.     
  209.   return in;
  210. }
  211.  
  212. template <class charT, class InputIterator >
  213. _TYPENAME time_get<charT,InputIterator>::iter_type
  214. time_get<charT,InputIterator>::do_get_date (InputIterator in,
  215.     InputIterator end, ios_base& io, ios_base::iostate& err, tm* time) const
  216. {
  217.   __RWSTD::time_reader<charT,InputIterator> reader(in,end,io);
  218.   err=ios_base::goodbit;
  219.  
  220.   // Parse according to pattern 0 (strftime '%x' -- default date pattern)
  221.   if (!reader.get_time_pattern(reader.get_patt_string(reader.timp,0),time))
  222.     err=ios_base::failbit;
  223.  
  224.   if (reader.reached_end)
  225.     err|=ios_base::eofbit;
  226.  
  227.   return in;
  228. }
  229.  
  230. template <class charT, class InputIterator >
  231. _TYPENAME time_get<charT,InputIterator>::iter_type
  232. time_get<charT,InputIterator>::do_get_weekday (InputIterator in,
  233.     InputIterator end, ios_base& io, ios_base::iostate& err, tm* time) const
  234. {
  235.   __RWSTD::time_reader<charT,InputIterator> reader(in,end,io);
  236.   int wd=reader.get_keyword(reader.get_day_map(reader.timp));
  237.   err=ios_base::goodbit;
  238.  
  239.   if (wd<0)
  240.     err=ios_base::failbit;
  241.   else
  242.     time->tm_wday=wd;
  243.  
  244.   if (reader.reached_end)
  245.     err|=ios_base::eofbit;
  246.  
  247.   return in;
  248. }
  249.  
  250. template <class charT, class InputIterator >
  251. _TYPENAME time_get<charT,InputIterator>::iter_type
  252. time_get<charT,InputIterator>::do_get_monthname (InputIterator in,
  253.     InputIterator end, ios_base& io, ios_base::iostate& err, tm* time) const
  254. {
  255.   __RWSTD::time_reader<charT,InputIterator> reader(in,end,io);
  256.   int mo=reader.get_keyword(reader.get_month_map(reader.timp));
  257.   err=ios_base::goodbit;
  258.  
  259.   if (mo<0)
  260.     err=ios_base::failbit;
  261.   else
  262.     time->tm_mon=mo;
  263.  
  264.   if (reader.reached_end)
  265.     err|=ios_base::eofbit;
  266.  
  267.   return in;
  268. }
  269.  
  270. template <class charT, class InputIterator >
  271. _TYPENAME time_get<charT,InputIterator>::iter_type
  272. time_get<charT,InputIterator>::do_get_year (InputIterator in,
  273.     InputIterator end, ios_base& io, ios_base::iostate& err, tm* time) const
  274. {
  275.   __RWSTD::time_reader<charT,InputIterator> reader(in,end,io);
  276.   int yr=reader.to_ulong(reader.get_int_digits());
  277.   err=ios_base::goodbit;
  278.  
  279.   // 2-digit year numbers are accepted, but are not treated specially, and so
  280.   // end up in the 1st century C.E.
  281.   if (reader.error)
  282.     err=ios_base::failbit;
  283.   else
  284.     time->tm_year=yr-1900;
  285.  
  286.   if (reader.reached_end)
  287.     err|=ios_base::eofbit;
  288.  
  289.   return in;
  290. }
  291.  
  292. // -----------------------------------------------------
  293. // Facet time_put<charT,InputIterator> member templates.
  294. // -----------------------------------------------------
  295.  
  296. template <class charT, class OutputIterator>
  297. locale::id time_put<charT,OutputIterator>::id;
  298.  
  299. template <class charT, class OutputIterator>
  300. time_put<charT,OutputIterator>::~time_put() { }
  301.  
  302. template <class charT, class OutputIterator>
  303. OutputIterator time_put<charT,OutputIterator>::put
  304.     (OutputIterator out, ios_base &io, charT fill, const tm *time,
  305.      const charT* pattern, const charT* patt_end) const
  306. {
  307.   size_t patt_len=patt_end-pattern;
  308.   char scratch[40];
  309.   char *narrow_patt=(patt_len<=sizeof scratch)? scratch : new char[patt_len];
  310.   
  311.   #ifndef _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE
  312.   use_facet<ctype<charT> >(io.getloc()).narrow(pattern,patt_end,' ',narrow_patt);
  313.   #else
  314.   use_facet(io.getloc(),(ctype<charT>*)0).narrow(pattern,patt_end,' ',narrow_patt);
  315.   #endif
  316.  
  317.   char *np=narrow_patt;
  318.   for (const charT* wp=pattern; wp<patt_end; wp++,np++)
  319.     if (*np!='%')
  320.       *out++=*wp;
  321.     else if (++wp<patt_end)
  322.       switch (*++np) {
  323.  
  324.        case 'O':
  325.         // POSIX-style modifier
  326.         if (++wp<patt_end)
  327.           out=do_put(out,io,fill,time,*++np,'O');
  328.         break;
  329.  
  330.        case '%':
  331.         // Literal percent sign
  332.         *out++=*wp;
  333.         break;
  334.  
  335.        default:
  336.         // Treat everything else as a time format specifier.
  337.         out=do_put(out,io,fill,time,*np,' ');
  338.       }
  339.  
  340.   if (narrow_patt!=scratch)
  341.     delete[] narrow_patt;
  342.  
  343.   return out;
  344. }
  345.  
  346. template <class charT, class OutputIterator>
  347. OutputIterator time_put<charT,OutputIterator>::do_put
  348.     (OutputIterator out, ios_base &io, charT fill, const tm *time,
  349.      char format, char modifier) const
  350. {
  351.   const __RWSTD::timepunct<charT>& timp =
  352.   #ifndef _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE
  353.       use_facet<__RWSTD::timepunct<charT> >(io.getloc());
  354.   #else
  355.       use_facet(io.getloc(),(__RWSTD::timepunct<charT>*)0);
  356.   #endif
  357.  
  358.   static const char do_as_pattern[]="xXcDrT";
  359.   const char *p=strchr(do_as_pattern,format);
  360.   if (p) {
  361.     // Catch formats implemented as calls to the pattern-based method before
  362.     // going to the expense of constructing a digit_writer.
  363.     unsigned i=p-do_as_pattern;
  364.     const _TYPENAME __RWSTD::timepunct<charT>::string_type& s =
  365.         __RWSTD::keyword_cracker<charT>::get_patt_string(timp,i);
  366.     return put(out,io,fill,time,s.c_str(),s.c_str()+s.length());
  367.   }
  368.  
  369.   __RWSTD::digit_writer<charT,OutputIterator> writer(out,io);
  370.   writer.width=0;
  371.  
  372.   if (modifier=='O') {
  373.     // Uppercase letter O (not zero) -- requests ordinal string if defined.
  374.     int n,m;
  375.     switch (format) {
  376.      case 'C':
  377.       // Exclusive Rogue Wave extension, let's you announce, "Welcome to the
  378.       // %OC century!"  (See note on unmodified 'C' below.)
  379.       n=(time->tm_year+1999)/100;
  380.       break;
  381.      case 'd':
  382.      case 'e':
  383.       n=time->tm_mday;
  384.       break;
  385.      case 'H':
  386.       n=time->tm_hour+1;
  387.       break;
  388.      case 'I':
  389.       n=time->tm_hour+1;
  390.       if (n>12)
  391.         n-=12;
  392.       break;
  393.      case 'm':
  394.       n=time->tm_mon+1;
  395.       break;
  396.      case 'M':
  397.       n=time->tm_min+1;
  398.       break;
  399.      case 'S':
  400.       n=time->tm_sec+1;
  401.       break;
  402.      case 'u':
  403.       n=time->tm_wday;
  404.       if (n==0) n=7;
  405.       break;
  406.      case 'w':
  407.       n=time->tm_wday;
  408.       break;
  409.      case 'U':
  410.       n=(time->tm_yday)/7;
  411.       break;
  412.      case 'W':
  413.       m=time->tm_wday-1; // Monday-based day of week
  414.       if (m<0) m+=7;
  415.       n=(time->tm_yday-m)/7;
  416.       break;
  417.      case 'y':
  418.       n=(time->tm_year%100)+1;
  419.       break;
  420.      default:
  421.       n=999; // Cause error output.
  422.     }
  423.  
  424.     writer.put_keyword(writer.get_ord_string(timp,n),fill);
  425.  
  426.   } else {
  427.     bool abbrev=false;
  428.     const _TYPENAME __RWSTD::timepunct<charT>::string_type *s=NULL;
  429.     //    _TYPENAME __RWSTD::timepunct<charT>::string_type tzs;
  430.     int n;
  431.  
  432.     writer.radix=10;
  433.     writer.separable=false;
  434.  
  435.     switch (format) {
  436.      case 'a':
  437.       abbrev=true;
  438.      case 'A':
  439.       // Week day name or abbreviation.
  440.       s=&writer.get_day_string(timp,time->tm_wday,abbrev);
  441.       break;
  442.  
  443.      case 'b':
  444.      case 'h':
  445.       abbrev=true;
  446.      case 'B':
  447.       // Month name or abbreviation.
  448.       s=&writer.get_month_string(timp,time->tm_mon,abbrev);
  449.       break;
  450.  
  451.      case 'C':
  452.       // Century.  Note that we begin the 20th century in 1901, not 1900.  The
  453.       // draft standard does not seem to address this controversy.
  454.       n=(time->tm_year+1999)/100;
  455.       break;
  456.  
  457.      case 'd':
  458.       // Day of month with leading zero.
  459.       writer.iprecision=2;
  460.      case 'e':
  461.       // Day of month with leading blank.
  462.       n=time->tm_mday;
  463.       writer.width=2;
  464.       break;
  465.  
  466.      case 'H':
  467.       // Hour (24-hour clock).
  468.       n=time->tm_hour;
  469.       writer.iprecision=2;
  470.       break;
  471.  
  472.      case 'I':
  473.       // Hour (12-hour clock, caller must append am/pm to resolve ambiguity).
  474.       n=time->tm_hour;
  475.       if (n==0)
  476.         n=12;
  477.       else if (n>12)
  478.         n-=12;
  479.       writer.iprecision=2;
  480.       break;
  481.  
  482.      case 'j':
  483.       // 3-digit day of year.
  484.       n=time->tm_yday+1;
  485.       writer.iprecision=3;
  486.       break;
  487.  
  488.      case 'm':
  489.       // Month number.
  490.       n=time->tm_mon+1;
  491.       writer.iprecision=2;
  492.       break;
  493.  
  494.      case 'M':
  495.       // Minutes.
  496.       n=time->tm_min;
  497.       writer.iprecision=2;
  498.       break;
  499.  
  500.      case 'n':
  501.       // Newline character.
  502.       *out++=writer.ctyp.widen('\n');
  503.       break;
  504.  
  505.      case 'p':
  506.       // ante/post meridian string.
  507.       s=&writer.get_ampm_string(timp,time->tm_hour==0 || time->tm_hour>12);
  508.       break;
  509.  
  510.      case 'S':
  511.       // Seconds.
  512.       n=time->tm_sec;
  513.       writer.iprecision=2;
  514.       break;
  515.  
  516.      case 't':
  517.       // Tab character.
  518.       *out++=writer.ctyp.widen('\t');
  519.       break;
  520.  
  521.      case 'u':
  522.       // Weekday (1-7, 1==Monday)
  523.       n=time->tm_wday;
  524.       if (n==0)
  525.         n=7;
  526.       break;
  527.  
  528.      case 'U':
  529.       // Week number of year (assuming weeks start on Sunday).
  530.       n=(time->tm_yday)/7;
  531.       writer.iprecision=2;
  532.       break;
  533.  
  534.      case 'w':
  535.       // Weekday (0-6, 0==Sunday).
  536.       n=time->tm_wday;
  537.       break;
  538.  
  539.      case 'W':
  540.       // Week number of year (assuming weeks start on Monday).
  541.       n=(time->tm_yday+(time->tm_wday==0? 6 : (time->tm_wday-1)))/7;
  542.       writer.iprecision=2;
  543.       break;
  544.  
  545.      case 'y':
  546.       // Year without century.
  547.       n=time->tm_year%100;
  548.       writer.iprecision=2;
  549.       break;
  550.         
  551.      case 'Y':
  552.       // Year with century.
  553.       n=time->tm_year+1900;
  554.       break;
  555.  
  556.      case 'Z':
  557.       // Time zone name 
  558.        //      tzs = __RWSTD::timepunct<charT>::string_type(
  559.        //          writer.ctyp.widen(tzname[time->tm_isdst ? 1 : 0]));
  560.        //      s = &tzs;
  561.       break;
  562.  
  563.      default:
  564.       // Everything else is an error.
  565.       s=&writer.get_day_string(timp,99,false);
  566.     }
  567.  
  568.     if (s)
  569.       writer.put_keyword(*s,fill);
  570.     else {
  571.       writer.digitize((unsigned long) n);
  572.       writer.put_digits(fill);
  573.     }
  574.   }
  575.  
  576.   return out;
  577. }
  578.  
  579.  
  580. // --------------------------------------------------------------------
  581. // Time input by-name member templates: time_get<charT,InputIterator>
  582. // --------------------------------------------------------------------
  583.  
  584. template <class charT, class InputIterator >
  585. time_get_byname<charT, InputIterator>::time_get_byname
  586.     (const char* /*name*/, size_t refs): time_get<charT,InputIterator>(refs)
  587. { }
  588.  
  589. template <class charT, class InputIterator>
  590. time_get_byname<charT, InputIterator>::~time_get_byname()
  591. { }
  592.  
  593. // --------------------------------------------------------------------
  594. // Time output by-name member templates: time_put<charT,InputIterator>
  595. // --------------------------------------------------------------------
  596.  
  597. template <class charT, class OutputIterator>
  598. time_put_byname<charT,OutputIterator>::time_put_byname
  599.     (const char* /*name*/, size_t refs): time_put<charT,OutputIterator>(refs)
  600. { }
  601.  
  602. template <class charT, class OutputIterator>
  603. time_put_byname<charT,OutputIterator>::~time_put_byname()
  604. { }
  605.  
  606.  
  607. #ifndef _RWSTD_NO_NAMESPACE
  608. #endif
  609.  
  610. #pragma option pop
  611. #endif /* __TIME_CC */
  612.